home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-03-27 | 50.9 KB | 1,190 lines | [TEXT/ROSA] |
- Common Lisp the Language, 2nd Edition
- -------------------------------------------------------------------------------
-
- 14. Sequences
-
- The type sequence encompasses both lists and vectors (one-dimensional arrays).
- While these are different data structures with different structural properties
- leading to different algorithmic uses, they do have a common property: each
- contains an ordered set of elements. Note that nil is considered to be a
- sequence of length zero.
-
- Some operations are useful on both lists and arrays because they deal with
- ordered sets of elements. One may ask the number of elements, reverse the
- ordering, extract a subsequence, and so on. For such purposes Common Lisp
- provides a set of generic functions on sequences.
-
- [change_begin]
- Note that this remark, predating the design of the Common Lisp Object System,
- uses the term ``generic'' in a generic sense, and not necessarily in the
- technical sense used by CLOS (see chapter 2).
- [change_end]
-
- elt reverse map remove
- length nreverse some remove-duplicates
- subseq concatenate every delete
- copy-seq position notany delete-duplicates
- fill find notevery substitute
- replace sort reduce nsubstitute
- count merge search mismatch
-
- Some of these operations come in more than one version. Such versions are
- indicated by adding a suffix (or occasionally a prefix) to the basic name of
- the operation. In addition, many operations accept one or more optional keyword
- arguments that can modify the operation in various ways.
-
- If the operation requires testing sequence elements according to some
- criterion, then the criterion may be specified in one of two ways. The basic
- operation accepts an item, and elements are tested for being eql to that item.
- (A test other than eql can be specified by the :test or :test-not keyword. It
- is an error to use both of these keywords in the same call.) The variants
- formed by adding -if and -if-not to the basic operation name do not take an
- item, but instead a one-argument predicate, and elements are tested for
- satisfying or not satisfying the predicate. As an example,
-
- (remove item sequence)
-
- returns a copy of sequence from which all elements eql to item have been
- removed;
-
- (remove item sequence :test #'equal)
-
- returns a copy of sequence from which all elements equal to item have been
- removed;
-
- (remove-if #'numberp sequence)
-
- returns a copy of sequence from which all numbers have been removed.
-
- If an operation tests elements of a sequence in any manner, the keyword
- argument :key, if not nil, should be a function of one argument that will
- extract from an element the part to be tested in place of the whole element.
- For example, the effect of the MacLisp expression (assq item seq) could be
- obtained by
-
- (find item sequence :test #'eq :key #'car)
-
- This searches for the first element of sequence whose car is eq to item.
-
- [change_begin]
- X3J13 voted in June 1988 (FUNCTION-TYPE) to allow the :key function to be
- only of type symbol or function; a lambda-expression is no longer acceptable as
- a functional argument. One must use the function special form or the
- abbreviation #' before a lambda-expression that appears as an explicit argument
- form.
- [change_end]
-
- For some operations it can be useful to specify the direction in which the
- sequence is conceptually processed. In this case the basic operation normally
- processes the sequence in the forward direction, and processing in the reverse
- direction is indicated by a non-nil value for the keyword argument :from-end.
- (The processing order specified by the :from-end is purely conceptual.
- Depending on the object to be processed and on the implementation, the actual
- processing order may be different. For this reason a user-supplied test
- function should be free of side effects.)
-
- Many operations allow the specification of a subsequence to be operated upon.
- Such operations have keyword arguments called :start and :end. These arguments
- should be integer indices into the sequence, with startend (it is an error if
- start>end). They indicate the subsequence starting with and including element
- start and up to but excluding element end. The length of the subsequence is
- therefore end-start. If start is omitted, it defaults to zero; and if end is
- omitted or nil, it defaults to the length of the sequence. Therefore if both
- start and end are omitted, the entire sequence is processed by default. For the
- most part, subsequence specification is permitted purely for the sake of
- efficiency; one could simply call subseq instead to extract the subsequence
- before operating on it. Note, however, that operations that calculate indices
- return indices into the original sequence, not into the subsequence:
-
- (position #\b "foobar" :start 2 :end 5) => 3
- (position #\b (subseq "foobar" 2 5)) => 1
-
- If two sequences are involved, then the keyword arguments :start1, :end1,
- :start2, and :end2 are used to specify separate subsequences for each sequence.
-
- [change_begin]
- X3J13 voted in June 1988 (SUBSEQ-OUT-OF-BOUNDS) (and further clarification
- was voted in January 1989 (RANGE-OF-START-AND-END-PARAMETERS) ) to specify
- that these rules apply not only to all built-in functions that have keyword
- parameters named :start, :start1, :start2, :end, :end1, or :end2 but also to
- functions such as subseq that take required or optional parameters that are
- documented as being named start or end.
-
- * A ``start'' argument must always be a non-negative integer and defaults
- to zero if not supplied; it is not permissible to pass nil as a ``start''
- argument.
-
- * An ``end'' argument must be either a non-negative integer or nil (which
- indicates the end of the sequence) and defaults to nil if not supplied;
- therefore supplying nil is equivalent to not supplying such an argument.
-
- * If the ``end'' argument is an integer, it must be no greater than the
- active length of the corresponding sequence (as returned by the function
- length).
-
- * The default value for the ``end'' argument is the active length of the
- corresponding sequence.
-
- * The ``start'' value (after defaulting, if necessary) must not be greater
- than the corresponding ``end'' value (after defaulting, if necessary).
-
- This may be summarized as follows. Let x be the sequence within which indices
- are to be considered. Let s be the ``start'' argument for that sequence of any
- standard function, whether explicitly specified or defaulted, through omission,
- to zero. Let e be the ``end'' argument for that sequence of any standard
- function, whether explicitly specified or defaulted, through omission or an
- explicitly passed nil value, to the active length of x, as returned by length.
- Then it is an error if the test (<= 0 s e (length x)) is not true.
- [change_end]
-
- For some functions, notably remove and delete, the keyword argument :count is
- used to specify how many occurrences of the item should be affected. If this is
- nil or is not supplied, all matching items are affected.
-
- In the following function descriptions, an element x of a sequence ``satisfies
- the test'' if any of the following holds:
-
- * A basic function was called, testfn was specified by the keyword :test,
- and (funcall testfn item (keyfn x)) is true.
-
- * A basic function was called, testfn was specified by the keyword
- :test-not, and (funcall testfn item (keyfn x)) is false.
-
- * An -if function was called, and (funcall predicate (keyfn x)) is true.
-
- * An -if-not function was called, and (funcall predicate (keyfn x)) is
- false.
-
- In each case keyfn is the value of the :key keyword argument (the default being
- the identity function). See, for example, remove.
-
- In the following function descriptions, two elements x and y taken from
- sequences ``match'' if either of the following holds:
-
- * testfn was specified by the keyword :test, and (funcall testfn (keyfn x)
- (keyfn y)) is true.
-
- * testfn was specified by the keyword :test-not, and (funcall testfn (keyfn
- x) (keyfn y)) is false.
-
- See, for example, search.
-
- [change_begin]
- X3J13 voted in June 1988 (FUNCTION-TYPE) to allow the testfn or predicate to
- be only of type symbol or function; a lambda-expression is no longer acceptable
- as a functional argument. One must use the function special form or the
- abbreviation #' before a lambda-expression that appears as an explicit argument
- form.
- [change_end]
-
- You may depend on the order in which arguments are given to testfn; this
- permits the use of non-commutative test functions in a predictable manner. The
- order of the arguments to testfn corresponds to the order in which those
- arguments (or the sequences containing those arguments) were given to the
- sequence function in question. If a sequence function gives two elements from
- the same sequence argument to testfn, they are given in the same order in which
- they appear in the sequence.
-
- Whenever a sequence function must construct and return a new vector, it always
- returns a simple vector (see section 2.5). Similarly, any strings constructed
- will be simple strings.
-
- [change_begin]
- X3J13 voted in January 1989 (TEST-NOT-IF-NOT) to deprecate the use of
- :test-not keyword arguments and -if-not functions. This means that these
- features are very likely to be retained in the forthcoming standard but are
- regarded as candidates for removal in a future revision of the ANSI standard.
- X3J13 also voted in January 1989 (FUNCTION-COMPOSITION) to add the complement
- function, intended to reduce or eliminate the need for these deprecated
- features. Time will tell. I note that many features in Fortran have been
- deprecated but very few indeed have actually been removed or altered
- incompatibly.
-
- [Function]
- complement fn
-
- Returns a function whose value is the same as that of not applied to the result
- of applying the function fn to the same arguments. One could define complement
- as follows:
-
- (defun complement (fn)
- #'(lambda (&rest arguments)
- (not (apply fn arguments))))
-
- One intended use of complement is to supplant the use of :test-not arguments
- and -if-not functions.
-
- (remove-if-not #'virtuous senators) ==
- (remove-if (complement #'virtuous) senators)
-
- (remove-duplicates telephone-book
- :test-not #'mismatch) ==
- (remove-duplicates telephone-book
- :test (complement #'mismatch))
-
- [change_end]
-
- -------------------------------------------------------------------------------
-
- * Simple Sequence Functions
- * Concatenating, Mapping, and Reducing Sequences
- * Modifying Sequences
- * Searching Sequences for Items
- * Sorting and Merging
-
- -------------------------------------------------------------------------------
-
- 14.1. Simple Sequence Functions
-
- Most of the following functions perform simple operations on a single sequence;
- make-sequence constructs a new sequence.
-
- [Function]
- elt sequence index
-
- This returns the element of sequence specified by index, which must be a
- non-negative integer less than the length of the sequence as returned by
- length. The first element of a sequence has index 0.
-
- (Note that elt observes the fill pointer in those vectors that have fill
- pointers. The array-specific function aref may be used to access vector
- elements that are beyond the vector's fill pointer.)
-
- setf may be used with elt to destructively replace a sequence element with a
- new value.
-
- [Function]
- subseq sequence start &optional end
-
- This returns the subsequence of sequence specified by start and end. subseq
- always allocates a new sequence for a result; it never shares storage with an
- old sequence. The result subsequence is always of the same type as the argument
- sequence.
-
- setf may be used with subseq to destructively replace a subsequence with a
- sequence of new values; see also replace.
-
- [Function]
- copy-seq sequence
-
- A copy is made of the argument sequence; the result is equalp to the argument
- but not eq to it.
-
- (copy-seq x) == (subseq x 0)
-
- but the name copy-seq is more perspicuous when applicable.
-
- [Function]
- length sequence
-
- The number of elements in sequence is returned as a non-negative integer. If
- the sequence is a vector with a fill pointer, the ``active length'' as
- specified by the fill pointer is returned (see section 17.5).
-
- [Function]
- reverse sequence
-
- The result is a new sequence of the same kind as sequence, containing the same
- elements but in reverse order. The argument is not modified.
-
- [Function]
- nreverse sequence
-
- The result is a sequence containing the same elements as sequence but in
- reverse order. The argument may be destroyed and re-used to produce the result.
- The result may or may not be eq to the argument, so it is usually wise to say
- something like (setq x (nreverse x)), because simply (nreverse x) is not
- guaranteed to leave a reversed value in x.
-
- [change_begin]
- X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) to clarify the
- permissible side effects of certain operations. When the sequence is a list,
- nreverse is permitted to perform a setf on any part, car or cdr, of the
- top-level list structure of that list. When the sequence is an array, nreverse
- is permitted to re-order the elements of the given array in order to produce
- the resulting array.
- [change_end]
-
- [Function]
- make-sequence type size &key :initial-element
-
- This returns a sequence of type type and of length size, each of whose elements
- has been initialized to the :initial-element argument. If specified, the
- :initial-element argument must be an object that can be an element of a
- sequence of type type. For example:
-
- (make-sequence '(vector double-float)
- 100
- :initial-element 1d0)
-
- If an :initial-element argument is not specified, then the sequence will be
- initialized in an implementation-dependent way.
-
- [change_begin]
- X3J13 voted in January 1989 (ARGUMENTS-UNDERSPECIFIED) to clarify that the
- type argument must be a type specifier, and the size argument must be a
- non-negative integer less than the value of array-dimension-limit.
-
- X3J13 voted in June 1989 (SEQUENCE-TYPE-LENGTH) to specify that make-sequence
- should signal an error if the sequence type specifies the number of elements
- and the size argument is different.
-
- X3J13 voted in March 1989 (CHARACTER-PROPOSAL) to specify that if type is
- string, the result is the same as if make-string had been called with the same
- size and :initial-element arguments.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 14.2. Concatenating, Mapping, and Reducing Sequences
-
- The functions in this section each operate on an arbitrary number of sequences
- except for reduce, which is included here because of its conceptual
- relationship to the mapping functions.
-
- [Function]
- concatenate result-type &rest sequences
-
- The result is a new sequence that contains all the elements of all the
- sequences in order. All of the sequences are copied from; the result does not
- share any structure with any of the argument sequences (in this concatenate
- differs from append). The type of the result is specified by result-type, which
- must be a subtype of sequence, as for the function coerce. It must be possible
- for every element of the argument sequences to be an element of a sequence of
- type result-type.
-
- If only one sequence argument is provided and it has the type specified by
- result-type, concatenate is required to copy the argument rather than simply
- returning it. If a copy is not required, but only possibly type conversion,
- then the coerce function may be appropriate.
-
- [change_begin]
- X3J13 voted in June 1989 (SEQUENCE-TYPE-LENGTH) to specify that concatenate
- should signal an error if the sequence type specifies the number of elements
- and the sum of the argument lengths is different.
- [change_end]
-
- [Function]
- map result-type function sequence &rest more-sequences
-
- The function must take as many arguments as there are sequences provided; at
- least one sequence must be provided. The result of map is a sequence such that
- element j is the result of applying function to element j of each of the
- argument sequences. The result sequence is as long as the shortest of the input
- sequences.
-
- If the function has side effects, it can count on being called first on all the
- elements numbered 0, then on all those numbered 1, and so on.
-
- The type of the result sequence is specified by the argument result-type (which
- must be a subtype of the type sequence), as for the function coerce. In
- addition, one may specify nil for the result type, meaning that no result
- sequence is to be produced; in this case the function is invoked only for
- effect, and map returns nil. This gives an effect similar to that of mapc.
-
- [change_begin]
- X3J13 voted in June 1989 (SEQUENCE-TYPE-LENGTH) to specify that map should
- signal an error if the sequence type specifies the number of elements and the
- minimum of the argument lengths is different.
-
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- -------------------------------------------------------------------------------
- Compatibility note: In MacLisp, Lisp Machine Lisp, Interlisp, and indeed even
- Lisp 1.5, the function map has always meant a non-value-returning version.
- However, standard computer science literature, including in particular the
- recent wave of papers on ``functional programming,'' have come to use map to
- mean what in the past Lisp implementations have called mapcar. To simplify
- things henceforth, Common Lisp follows current usage, and what was formerly
- called map is named mapl in Common Lisp.
- -------------------------------------------------------------------------------
-
- For example:
-
- (map 'list #'- '(1 2 3 4)) => (-1 -2 -3 -4)
- (map 'string
- #'(lambda (x) (if (oddp x) #\1 #\0))
- '(1 2 3 4))
- => "1010"
-
- [change_begin]
-
- [Function]
- map-into result-sequence function &rest sequences
-
- X3J13 voted in June 1989 (MAP-INTO) to add the function map-into. It
- destructively modifies the result-sequence to contain the results of applying
- function to corresponding elements of the argument sequences in turn; it then
- returns result-sequence.
-
- The arguments result-sequence and each element of sequences can each be either
- a list or a vector (one-dimensional array). The function must accept at least
- as many arguments as the number of argument sequences supplied to map-into. If
- result-sequence and the other argument sequences are not all the same length,
- the iteration terminates when the shortest sequence is exhausted. If
- result-sequence is a vector with a fill pointer, the fill pointer is ignored
- when deciding how many iterations to perform, and afterwards the fill pointer
- is set to the number of times the function was applied.
-
- If the function has side effects, it can count on being called first on all the
- elements numbered 0, then on all those numbered 1, and so on.
-
- If result-sequence is longer than the shortest element of sequences, extra
- elements at the end of result-sequence are unchanged.
-
- The function map-into differs from map in that it modifies an existing sequence
- rather than creating a new one. In addition, map-into can be called with only
- two arguments (result-sequence and function), while map requires at least three
- arguments.
-
- If result-sequence is nil, map-into immediately returns nil, because nil is a
- sequence of length zero.
- [change_end]
-
- [Function]
- some predicate sequence &rest more-sequences
- every predicate sequence &rest more-sequences
- notany predicate sequence &rest more-sequences
- notevery predicate sequence &rest more-sequences
-
- These are all predicates. The predicate must take as many arguments as there
- are sequences provided. The predicate is first applied to the elements with
- index 0 in each of the sequences, and possibly then to the elements with index
- 1, and so on, until a termination criterion is met or the end of the shortest
- of the sequences is reached.
-
- If the predicate has side effects, it can count on being called first on all
- the elements numbered 0, then on all those numbered 1, and so on.
-
- some returns as soon as any invocation of predicate returns a non-nil value;
- some returns that value. If the end of a sequence is reached, some returns nil.
- Thus, considered as a predicate, it is true if some invocation of predicate is
- true.
-
- every returns nil as soon as any invocation of predicate returns nil. If the
- end of a sequence is reached, every returns a non-nil value. Thus, considered
- as a predicate, it is true if every invocation of predicate is true.
-
- notany returns nil as soon as any invocation of predicate returns a non-nil
- value. If the end of a sequence is reached, notany returns a non-nil value.
- Thus, considered as a predicate, it is true if no invocation of predicate is
- true.
-
- notevery returns a non-nil value as soon as any invocation of predicate returns
- nil. If the end of a sequence is reached, notevery returns nil. Thus,
- considered as a predicate, it is true if not every invocation of predicate is
- true.
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- -------------------------------------------------------------------------------
- Compatibility note: The order of the arguments here is not compatible with
- Interlisp and Lisp Machine Lisp. This is to stress the similarity of these
- functions to map. The functions are therefore extended here to functions of
- more than one argument, and to multiple sequences.
- -------------------------------------------------------------------------------
-
- [Function]
- reduce function sequence &key :from-end :start :end :initial-value
-
- The reduce function combines all the elements of a sequence using a binary
- operation; for example, using + one can add up all the elements.
-
- The specified subsequence of the sequence is combined or ``reduced'' using the
- function, which must accept two arguments. The reduction is left-associative,
- unless the :from-end argument is true (it defaults to nil), in which case it is
- right-associative. If an :initial-value argument is given, it is logically
- placed before the subsequence (after it if :from-end is true) and included in
- the reduction operation.
-
- If the specified subsequence contains exactly one element and the keyword
- argument :initial-value is not given, then that element is returned and the
- function is not called. If the specified subsequence is empty and an
- :initial-value is given, then the :initial-value is returned and the function
- is not called.
-
- If the specified subsequence is empty and no :initial-value is given, then the
- function is called with zero arguments, and reduce returns whatever the
- function does. (This is the only case where the function is called with other
- than two arguments.)
-
- (reduce #'+ '(1 2 3 4)) => 10
- (reduce #'- '(1 2 3 4)) == (- (- (- 1 2) 3) 4) => -8
- (reduce #'- '(1 2 3 4) :from-end t) ;Alternating sum
- == (- 1 (- 2 (- 3 4))) => -2
- (reduce #'+ '()) => 0
- (reduce #'+ '(3)) => 3
- (reduce #'+ '(foo)) => foo
- (reduce #'list '(1 2 3 4)) => (((1 2) 3) 4)
- (reduce #'list '(1 2 3 4) :from-end t) => (1 (2 (3 4)))
- (reduce #'list '(1 2 3 4) :initial-value 'foo)
- => ((((foo 1) 2) 3) 4)
- (reduce #'list '(1 2 3 4)
- :from-end t :initial-value 'foo)
- => (1 (2 (3 (4 foo))))
-
- If the function produces side effects, the order of the calls to the function
- can be correctly predicted from the reduction ordering demonstrated above.
-
- [change_begin]
- The name ``reduce'' for this function is borrowed from APL.
-
- X3J13 voted in March 1988 (REDUCE-ARGUMENT-EXTRACTION) to extend the reduce
- function to take an additional keyword argument named :key. As usual, this
- argument defaults to the identity function. The value of this argument must be
- a function that accepts at least one argument. This function is applied once to
- each element of the sequence that is to participate in the reduction operation,
- in the order implied by the :from-end argument; the values returned by this
- function are combined by the reduction function. However, the :key function is
- not applied to the :initial-value argument (if any).
-
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 14.3. Modifying Sequences
-
- Each of these functions alters the contents of a sequence or produces an
- altered copy of a given sequence.
-
- [Function]
- fill sequence item &key :start :end
-
- The sequence is destructively modified by replacing each element of the
- subsequence specified by the :start and :end parameters with the item. The item
- may be any Lisp object but must be a suitable element for the sequence. The
- item is stored into all specified components of the sequence, beginning at the
- one specified by the :start index (which defaults to zero), up to but not
- including the one specified by the :end index (which defaults to the length of
- the sequence). fill returns the modified sequence. For example:
-
- (setq x (vector 'a 'b 'c 'd 'e)) => #(a b c d e)
- (fill x 'z :start 1 :end 3) => #(a z z d e)
- and now x => #(a z z d e)
- (fill x 'p) => #(p p p p p)
- and now x => #(p p p p p)
-
- [Function]
- replace sequence1 sequence2 &key :start1 :end1 :start2 :end2
-
- The sequence sequence1 is destructively modified by copying successive elements
- into it from sequence2. The elements of sequence2 must be of a type that may be
- stored into sequence1. The subsequence of sequence2 specified by :start2 and
- :end2 is copied into the subsequence of sequence1 specified by :start1 and
- :end1. (The arguments :start1 and :start2 default to zero. The arguments :end1
- and :end2 default to nil, meaning the end of the appropriate sequence.) If
- these subsequences are not of the same length, then the shorter length
- determines how many elements are copied; the extra elements near the end of the
- longer subsequence are not involved in the operation. The number of elements
- copied may be expressed as:
-
- (min (- end1 start1) (- end2 start2))
-
- The value returned by replace is the modified sequence1.
-
- If sequence1 and sequence2 are the same (eq) object and the region being
- modified overlaps the region being copied from, then it is as if the entire
- source region were copied to another place and only then copied back into the
- target region. However, if sequence1 and sequence2 are not the same, but the
- region being modified overlaps the region being copied from (perhaps because of
- shared list structure or displaced arrays), then after the replace operation
- the subsequence of sequence1 being modified will have unpredictable contents.
-
- [Function]
-
- remove item sequence &key :from-end :test :test-not
- :start :end :count :key
- remove-if predicate sequence &key :from-end
- :start :end :count :key
- remove-if-not predicate sequence &key :from-end
- :start :end :count :key
-
- The result is a sequence of the same kind as the argument sequence that has the
- same elements except that those in the subsequence delimited by :start and :end
- and satisfying the test (see above) have been removed. This is a
- non-destructive operation; the result is a copy of the input sequence, save
- that some elements are not copied. Elements not removed occur in the same order
- in the result as they did in the argument.
-
- The :count argument, if supplied, limits the number of elements removed; if
- more than :count elements satisfy the test, then of these elements only the
- leftmost are removed, as many as specified by :count.
-
- [change_begin]
- X3J13 voted in January 1989 (RANGE-OF-COUNT-KEYWORD) to clarify that the
- :count argument must be either nil or an integer, and that supplying a negative
- integer produces the same behavior as supplying zero.
- [change_end]
-
- A non-nil :from-end specification matters only when the :count argument is
- provided; in that case only the rightmost :count elements satisfying the test
- are removed. For example:
-
- (remove 4 '(1 2 4 1 3 4 5)) => (1 2 1 3 5)
- (remove 4 '(1 2 4 1 3 4 5) :count 1) => (1 2 1 3 4 5)
- (remove 4 '(1 2 4 1 3 4 5) :count 1 :from-end t)
- => (1 2 4 1 3 5)
- (remove 3 '(1 2 4 1 3 4 5) :test #'>) => (4 3 4 5)
- (remove-if #'oddp '(1 2 4 1 3 4 5)) => (2 4 4)
- (remove-if #'evenp '(1 2 4 1 3 4 5) :count 1 :from-end t)
- => (1 2 4 1 3 5)
-
- The result of remove may share with the argument sequence; a list result may
- share a tail with an input list, and the result may be eq to the input sequence
- if no elements need to be removed.
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- [Function]
-
- delete item sequence &key :from-end :test :test-not
- :start :end :count :key
- delete-if predicate sequence &key :from-end
- :start :end :count :key
- delete-if-not predicate sequence &key :from-end
- :start :end :count :key
-
- This is the destructive counterpart to remove. The result is a sequence of the
- same kind as the argument sequence that has the same elements except that those
- in the subsequence delimited by :start and :end and satisfying the test (see
- above) have been deleted. This is a destructive operation. The argument
- sequence may be destroyed and used to construct the result; however, the result
- may or may not be eq to sequence. Elements not deleted occur in the same order
- in the result as they did in the argument.
-
- The :count argument, if supplied, limits the number of elements deleted; if
- more than :count elements satisfy the test, then of these elements only the
- leftmost are deleted, as many as specified by :count.
-
- [change_begin]
- X3J13 voted in January 1989 (RANGE-OF-COUNT-KEYWORD) to clarify that the
- :count argument must be either nil or an integer, and that supplying a negative
- integer produces the same behavior as supplying zero.
- [change_end]
-
- A non-nil :from-end specification matters only when the :count argument is
- provided; in that case only the rightmost :count elements satisfying the test
- are deleted. For example:
-
- (delete 4 '(1 2 4 1 3 4 5)) => (1 2 1 3 5)
- (delete 4 '(1 2 4 1 3 4 5) :count 1) => (1 2 1 3 4 5)
- (delete 4 '(1 2 4 1 3 4 5) :count 1 :from-end t)
- => (1 2 4 1 3 5)
- (delete 3 '(1 2 4 1 3 4 5) :test #'>) => (4 3 4 5)
- (delete-if #'oddp '(1 2 4 1 3 4 5)) => (2 4 4)
- (delete-if #'evenp '(1 2 4 1 3 4 5) :count 1 :from-end t)
- => (1 2 4 1 3 5)
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
-
- X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) to clarify the
- permissible side effects of certain operations. When the sequence is a list,
- delete is permitted to perform a setf on any part, car or cdr, of the top-level
- list structure of that list. When the sequence is an array, delete is permitted
- to alter the dimensions of the given array and to slide some of its elements
- into new positions without permuting them in order to produce the resulting
- array.
-
- Furthermore, (delete-if predicate sequence ...) is required to behave exactly
- like
-
- (delete nil sequence
- :test #'(lambda (unused item)
- (declare (ignore unused))
- (funcall predicate item))
- ...)
-
- [change_end]
-
- -------------------------------------------------------------------------------
- Compatibility note: In MacLisp, the delete function uses an equal comparison
- rather than eql, which is the default test for delete in Common Lisp. Where in
- MacLisp one would write (delete x y), one must in Common Lisp write (delete x y
- :test #'equal) to get the completely identical effect. Similarly, one can get
- the precise effect, and no more, of the MacLisp (delq x y) by writing in Common
- Lisp (delete x y :test #'eq).
- -------------------------------------------------------------------------------
-
- [Function]
-
- remove-duplicates sequence &key :from-end :test :test-not
- :start :end :key
- delete-duplicates sequence &key :from-end :test :test-not
- :start :end :key
-
- The elements of sequence are compared pairwise, and if any two match, then the
- one occurring earlier in the sequence is discarded (but if the :from-end
- argument is true, then the one later in the sequence is discarded). The result
- is a sequence of the same kind as the argument sequence with enough elements
- removed so that no two of the remaining elements match. The order of the
- elements remaining in the result is the same as the order in which they appear
- in sequence.
-
- remove-duplicates is the non-destructive version of this operation. The result
- of remove-duplicates may share with the argument sequence; a list result may
- share a tail with an input list, and the result may be eq to the input sequence
- if no elements need to be removed.
-
- delete-duplicates may destroy the argument sequence.
-
- Some examples:
-
- (remove-duplicates '(a b c b d d e)) => (a c b d e)
- (remove-duplicates '(a b c b d d e) :from-end t) => (a b c d e)
- (remove-duplicates '((foo #\a) (bar #\%) (baz #\A))
- :test #'char-equal :key #'cadr)
- => ((bar #\%) (baz #\A))
- (remove-duplicates '((foo #\a) (bar #\%) (baz #\A))
- :test #'char-equal :key #'cadr :from-end t)
- => ((foo #\a) (bar #\%))
-
- These functions are useful for converting a sequence into a canonical form
- suitable for representing a set.
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
-
- X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) to clarify the
- permissible side effects of certain operations. When the sequence is a list,
- delete-duplicates is permitted to perform a setf on any part, car or cdr, of
- the top-level list structure of that list. When the sequence is an array,
- delete-duplicates is permitted to alter the dimensions of the given array and
- to slide some of its elements into new positions without permuting them in
- order to produce the resulting array.
- [change_end]
-
- [Function]
-
- substitute newitem olditem sequence &key :from-end :test :test-not
- :start :end :count :key
- substitute-if newitem test sequence &key :from-end
- :start :end :count :key
- substitute-if-not newitem test sequence &key :from-end
- :start :end :count :key
-
- The result is a sequence of the same kind as the argument sequence that has the
- same elements except that those in the subsequence delimited by :start and :end
- and satisfying the test (see above) have been replaced by newitem. This is a
- non-destructive operation; the result is a copy of the input sequence, save
- that some elements are changed.
-
- The :count argument, if supplied, limits the number of elements altered; if
- more than :count elements satisfy the test, then of these elements only the
- leftmost are replaced, as many as specified by :count.
-
- [change_begin]
- X3J13 voted in January 1989 (RANGE-OF-COUNT-KEYWORD) to clarify that the
- :count argument must be either nil or an integer, and that supplying a negative
- integer produces the same behavior as supplying zero.
- [change_end]
-
- A non-nil :from-end specification matters only when the :count argument is
- provided; in that case only the rightmost :count elements satisfying the test
- are replaced. For example:
-
- (substitute 9 4 '(1 2 4 1 3 4 5)) => (1 2 9 1 3 9 5)
- (substitute 9 4 '(1 2 4 1 3 4 5) :count 1) => (1 2 9 1 3 4 5)
- (substitute 9 4 '(1 2 4 1 3 4 5) :count 1 :from-end t)
- => (1 2 4 1 3 9 5)
- (substitute 9 3 '(1 2 4 1 3 4 5) :test #'>) => (9 9 4 9 3 4 5)
- (substitute-if 9 #'oddp '(1 2 4 1 3 4 5)) => (9 2 4 9 9 4 9)
- (substitute-if 9 #'evenp '(1 2 4 1 3 4 5) :count 1 :from-end t)
- => (1 2 4 1 3 9 5)
-
- The result of substitute may share with the argument sequence; a list result
- may share a tail with an input list, and the result may be eq to the input
- sequence if no elements need to be changed.
-
- See also subst, which performs substitutions throughout a tree.
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- [Function]
-
- nsubstitute newitem olditem sequence &key :from-end :test :test-not
- :start :end :count :key
- nsubstitute-if newitem test sequence &key :from-end
- :start :end :count :key
- nsubstitute-if-not newitem test sequence &key :from-end
- :start :end :count :key
-
- This is the destructive counterpart to substitute. The result is a sequence of
- the same kind as the argument sequence that has the same elements except that
- those in the subsequence delimited by :start and :end and satisfying the test
- (see above) have been replaced by newitem. This is a destructive operation. The
- argument sequence may be destroyed and used to construct the result; however,
- the result may or may not be eq to sequence.
-
- See also nsubst, which performs destructive substitutions throughout a tree.
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
-
- X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) to clarify the
- permissible side effects of certain operations. When the sequence is a list,
- nsubstitute or nsubstitute-if is required to perform a setf on any car of the
- top-level list structure of that list whose old contents must be replaced with
- newitem but is forbidden to perform a setf on any cdr of the list. When the
- sequence is an array, nsubstitute or nsubstitute-if is required to perform a
- setf on any element of the array whose old contents must be replaced with
- newitem. These functions, therefore, may successfully be used solely for
- effect, the caller discarding the returned value (though some programmers find
- this stylistically distasteful).
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 14.4. Searching Sequences for Items
-
- Each of these functions searches a sequence to locate one or more elements
- satisfying some test.
-
- [Function]
-
- find item sequence &key :from-end :test :test-not :start :end :key
- find-if predicate sequence &key :from-end :start :end :key
- find-if-not predicate sequence &key :from-end :start :end :key
-
- If the sequence contains an element satisfying the test, then the leftmost such
- element is returned; otherwise nil is returned.
-
- If :start and :end keyword arguments are given, only the specified subsequence
- of sequence is searched.
-
- If a non-nil :from-end keyword argument is specified, then the result is the
- rightmost element satisfying the test.
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- [Function]
-
- position item sequence &key :from-end :test :test-not
- :start :end :key
- position-if predicate sequence &key :from-end
- :start :end :key
- position-if-not predicate sequence &key :from-end
- :start :end :key
-
- If the sequence contains an element satisfying the test, then the index within
- the sequence of the leftmost such element is returned as a non-negative
- integer; otherwise nil is returned.
-
- If :start and :end keyword arguments are given, only the specified subsequence
- of sequence is searched. However, the index returned is relative to the entire
- sequence, not to the subsequence.
-
- If a non-nil :from-end keyword argument is specified, then the result is the
- index of the rightmost element satisfying the test. (The index returned,
- however, is an index from the left-hand end, as usual.)
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
-
- Here is a simple piece of code that uses several of the sequence functions,
- notably position-if and find-if, to process strings. Note one use of loop as
- well.
-
- (defun debug-palindrome (s)
- (flet ((match (x) (char-equal (first x) (third x))))
- (let* ((pairs (loop for c across s
- for j from 0
- when (alpha-char-p c)
- collect (list c j)))
- (quads (mapcar #'append pairs (reverse pairs)))
- (diffpos (position-if (complement #'match) quads)))
- (when diffpos
- (let* ((diff (elt quads diffpos))
- (same (find-if #'match quads
- :start (+ diffpos 1))))
- (if same
- (format nil
- "/~A/ (at ~D) is not the reverse of /~A/"
- (subseq s (second diff) (second same))
- (second diff)
- (subseq s (+ (fourth same) 1)
- (+ (fourth diff) 1)))
- "This palindrome is completely messed up!"))))))
-
- Here is an example of its behavior.
-
- (setq panama ;A putative palindrome?
- "A man, a plan, a canoe, pasta, heros, rajahs,
- a coloratura, maps, waste, percale, macaroni, a gag,
- a banana bag, a tan, a tag, a banana bag again
- (or a camel), a crepe, pins, Spam, a rut, a Rolo,
- cash, a jar, sore hats, a peon, a canal-Panama!")
-
- (debug-palindrome panama)
- => "/wast/ (at 73) is not the reverse of /, pins/"
-
- (replace panama "snipe" :start1 73) ;Repair it
- => "A man, a plan, a canoe, pasta, heros, rajahs,
- a coloratura, maps, snipe, percale, macaroni, a gag,
- a banana bag, a tan, a tag, a banana bag again
- (or a camel), a crepe, pins, Spam, a rut, a Rolo,
- cash, a jar, sore hats, a peon, a canal-Panama!"
-
- (debug-palindrome panama) => nil ;Copacetic-a true palindrome
-
- (debug-palindrome "Rubber baby buggy bumpers")
- => "/Rubber / (at 0) is not the reverse of /umpers/"
-
- (debug-palindrome "Common Lisp: The Language")
- => "/Commo/ (at 0) is not the reverse of /guage/"
-
- (debug-palindrome "Complete mismatches are hard to find")
- =>
- "/Complete mism/ (at 0) is not the reverse of /re hard to find/"
-
- (debug-palindrome "Waltz, nymph, for quick jigs vex Bud")
- => "This palindrome is completely messed up!"
-
- (debug-palindrome "Doc, note: I dissent. A fast never
- prevents a fatness. I diet on cod.")
- =>nil ;Another winner
-
- (debug-palindrome "Top step's pup's pet spot") => nil
-
- [change_end]
-
- [Function]
-
- count item sequence &key :from-end :test :test-not :start :end :key
- count-if predicate sequence &key :from-end :start :end :key
- count-if-not predicate sequence &key :from-end :start :end :key
-
- The result is always a non-negative integer, the number of elements in the
- specified subsequence of sequence satisfying the test.
-
- The :from-end argument does not affect the result returned; it is accepted
- purely for compatibility with other sequence functions.
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- [Function]
- mismatch sequence1 sequence2 &key :from-end :test :test-not :key :start1
- :start2 :end1 :end2
-
- The specified subsequences of sequence1 and sequence2 are compared
- element-wise. If they are of equal length and match in every element, the
- result is nil. Otherwise, the result is a non-negative integer. This result is
- the index within sequence1 of the leftmost position at which the two
- subsequences fail to match; or, if one subsequence is shorter than and a
- matching prefix of the other, the result is the index relative to sequence1
- beyond the last position tested.
-
- If a non-nil :from-end keyword argument is given, then one plus the index of
- the rightmost position in which the sequences differ is returned. In effect,
- the (sub)sequences are aligned at their right-hand ends; then, the last
- elements are compared, the penultimate elements, and so on. The index returned
- is again an index relative to sequence1.
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- [Function]
- search sequence1 sequence2 &key :from-end :test :test-not :key :start1 :start2
- :end1 :end2
-
- A search is conducted for a subsequence of sequence2 that element-wise matches
- sequence1. If there is no such subsequence, the result is nil; if there is, the
- result is the index into sequence2 of the leftmost element of the leftmost such
- matching subsequence.
-
- If a non-nil :from-end keyword argument is given, the index of the leftmost
- element of the rightmost matching subsequence is returned.
-
- The implementation may choose to search the sequence in any order; there is no
- guarantee on the number of times the test is made. For example, search with a
- non-nil :from-end argument might actually search a list from left to right
- instead of from right to left (but in either case would return the rightmost
- matching subsequence, of course). Therefore it is a good idea for a
- user-supplied predicate to be free of side effects.
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 14.5. Sorting and Merging
-
- These functions may destructively modify argument sequences in order to put a
- sequence into sorted order or to merge two already sorted sequences.
-
- [Function]
- sort sequence predicate &key :key
- stable-sort sequence predicate &key :key
-
- The sequence is destructively sorted according to an order determined by the
- predicate. The predicate should take two arguments, and return non-nil if and
- only if the first argument is strictly less than the second (in some
- appropriate sense). If the first argument is greater than or equal to the
- second (in the appropriate sense), then the predicate should return nil.
-
- The sort function determines the relationship between two elements by giving
- keys extracted from the elements to the predicate. The :key argument, when
- applied to an element, should return the key for that element. The :key
- argument defaults to the identity function, thereby making the element itself
- be the key.
-
- The :key function should not have any side effects. A useful example of a :key
- function would be a component selector function for a defstruct structure, used
- in sorting a sequence of structures.
-
- (sort a p :key s)
- == (sort a #'(lambda (x y) (p (s x) (s y))))
-
- While the above two expressions are equivalent, the first may be more efficient
- in some implementations for certain types of arguments. For example, an
- implementation may choose to apply s to each item just once, putting the
- resulting keys into a separate table, and then sort the parallel tables, as
- opposed to applying s to an item every time just before applying the predicate.
-
- If the :key and predicate functions always return, then the sorting operation
- will always terminate, producing a sequence containing the same elements as the
- original sequence (that is, the result is a permutation of sequence). This is
- guaranteed even if the predicate does not really consistently represent a total
- order (in which case the elements will be scrambled in some unpredictable way,
- but no element will be lost). If the :key function consistently returns
- meaningful keys, and the predicate does reflect some total ordering criterion
- on those keys, then the elements of the result sequence will be properly sorted
- according to that ordering.
-
- The sorting operation performed by sort is not guaranteed stable. Elements
- considered equal by the predicate may or may not stay in their original order.
- (The predicate is assumed to consider two elements x and y to be equal if
- (funcall predicate x y) and (funcall predicate y x) are both false.) The
- function stable-sort guarantees stability but may be slower than sort in some
- situations.
-
- The sorting operation may be destructive in all cases. In the case of an array
- argument, this is accomplished by permuting the elements in place. In the case
- of a list, the list is destructively reordered in the same manner as for
- nreverse. Thus if the argument should not be destroyed, the user must sort a
- copy of the argument.
-
- Should execution of the :key function or the predicate cause an error, the
- state of the list or array being sorted is undefined. However, if the error is
- corrected, the sort will, of course, proceed correctly.
-
- Note that since sorting requires many comparisons, and thus many calls to the
- predicate, sorting will be much faster if the predicate is a compiled function
- rather than interpreted.
-
- An example:
-
- (setq foovector (sort foovector #'string-lessp :key #'car))
-
- If foovector contained these items before the sort
-
- ("Tokens" "The Lion Sleeps Tonight")
- ("Carpenters" "Close to You")
- ("Rolling Stones" "Brown Sugar")
- ("Beach Boys" "I Get Around")
- ("Mozart" "Eine Kleine Nachtmusik" (K 525))
- ("Beatles" "I Want to Hold Your Hand")
-
- then after the sort foovector would contain
-
- ("Beach Boys" "I Get Around")
- ("Beatles" "I Want to Hold Your Hand")
- ("Carpenters" "Close to You")
- ("Mozart" "Eine Kleine Nachtmusik" (K 525))
- ("Rolling Stones" "Brown Sugar")
- ("Tokens" "The Lion Sleeps Tonight")
-
- [change_begin]
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- [Function]
- merge result-type sequence1 sequence2 predicate &key :key
-
- The sequences sequence1 and sequence2 are destructively merged according to an
- order determined by the predicate. The result is a sequence of type
- result-type, which must be a subtype of sequence, as for the function coerce.
- The predicate should take two arguments and return non-nil if and only if the
- first argument is strictly less than the second (in some appropriate sense). If
- the first argument is greater than or equal to the second (in the appropriate
- sense), then the predicate should return nil.
-
- The merge function determines the relationship between two elements by giving
- keys extracted from the elements to the predicate. The :key function, when
- applied to an element, should return the key for that element; the :key
- function defaults to the identity function, thereby making the element itself
- be the key.
-
- The :key function should not have any side effects. A useful example of a :key
- function would be a component selector function for a defstruct structure, used
- to merge a sequence of structures.
-
- If the :key and predicate functions always return, then the merging operation
- will always terminate. The result of merging two sequences x and y is a new
- sequence z, such that the length of z is the sum of the lengths of x and y, and
- z contains all the elements of x and y. If x1 and x2 are two elements of x, and
- x1 precedes x2 in x, then x1 precedes x2 in z, and similarly for elements of y.
- In short, z is an interleaving of x and y.
-
- Moreover, if x and y were correctly sorted according to the predicate, then z
- will also be correctly sorted, as shown in this example.
-
- (merge 'list '(1 3 4 6 7) '(2 5 8) #'<) => (1 2 3 4 5 6 7 8)
-
- If x or y is not so sorted then z will not be sorted, but will nevertheless be
- an interleaving of x and y.
-
- The merging operation is guaranteed stable; if two or more elements are
- considered equal by the predicate, then the elements from sequence1 will
- precede those from sequence2 in the result. (The predicate is assumed to
- consider two elements x and y to be equal if (funcall predicate x y) and
- (funcall predicate y x) are both false.) For example:
-
- (merge 'string "BOY" "nosy" #'char-lessp) => "BnOosYy"
-
- The result can not be "BnoOsYy", "BnOosyY", or "BnoOsyY". The function
- char-lessp ignores case, and so considers the characters Y and y to be equal,
- for example; the stability property then guarantees that the character from the
- first argument (Y) must precede the one from the second argument (y).
-
- [change_begin]
- X3J13 voted in June 1989 (SEQUENCE-TYPE-LENGTH) to specify that merge should
- signal an error if the sequence type specifies the number of elements and the
- sum of the lengths of the two sequence arguments is different.
-
- X3J13 voted in January 1989 (MAPPING-DESTRUCTIVE-INTERACTION) to restrict
- user side effects; see section 7.9.
- [change_end]
-
- -------------------------------------------------------------------------------
-
-
-